/*
 * Copyright (c) 2009-2010 VSC co.,Ltd. All rights reserved.
 */
package org.googlecode.viewt.core.tools.po;

import org.apache.commons.cli.CommandLine;
import org.apache.commons.cli.CommandLineParser;
import org.apache.commons.cli.GnuParser;
import org.apache.commons.cli.OptionBuilder;
import org.apache.commons.cli.Options;
import org.apache.commons.cli.ParseException;
import org.googlecode.viewt.core.tools.dao.BaseServiceGenerator;
import org.googlecode.viewt.core.tools.dao.BeanConfigGenerator;
import org.googlecode.viewt.core.tools.dao.ConstantGenerator;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * po generator
 * 
 * @author <a href="mailto:lizhengle@hotmail.com">Steven Li</a>
 */

public class POGenerateCommand {

	private static Logger logger = LoggerFactory.getLogger(POGenerateCommand.class);
	public static final String OPT_POCFG_FILE = "i";
	public static final String OPT_DEP_POFILES = "dep";
	public static final String OPT_IMP_DEST = "imp";
	public static final String OPT_API_DEST = "api";
	public static final String OPT_CFG_DEST = "cfg";
	public static final String OPT_NOT_GENDESC_CLASS = "nodesc";
	public static final String OPT_NOT_GENDAO_CLASS = "nodao";
	public static final String OPT_PREFIX_PACKAGE = "prepack";
	public static final String OPT_COPYRIGHT = "copyright";
	public static final String OPT_AUTHOR = "author";
	private String poCfgFile = null;

	private String[] dependCfgFiles = null;

	private String impDestPath = null;

	private String apiDestPath = null;

	private String cfgDestPath = null;

	private boolean genDescClass = true;

	private boolean genDAOClass = true;

	private String prePackName = "com.vsc";

	private String copyright = null;

	private String author = null;

	private POConfigRepository poRepository;

	public POGenerateCommand() {
		prePackName = "com.vsc";
		copyright = "";
		author = "Steven LI";
		poRepository = new POConfigRepository();
	}

	public void parseArgs(String[] args) throws ParseException {

		CommandLineParser parser = new GnuParser();

		//		
		Options opt = new Options();
		CommandLine cmdLine;

		// options.addOption(OptionBuilder.create("i"));
		opt.addOption(OptionBuilder.hasArg().isRequired().withDescription(
				"PO config file name by which to generate").create("i"));
		//		
		opt.addOption(OptionBuilder.hasArg().hasArgs().withDescription(
				"dependent PO config files").create("dep"));

		opt.addOption(OptionBuilder.hasArg().isRequired().withDescription(
				"path to output implementation class file").create("imp"));

		opt.addOption(OptionBuilder.hasArg().isRequired().withDescription(
				"path to output implementation class file").create("api"));

		opt.addOption(OptionBuilder.hasArg().withDescription(
				"path to output implementation class file").create("cfg"));

		opt.addOption(OptionBuilder.hasArg().withDescription(
				"do not generate PO descriptor class").create("nodesc"));

		opt.addOption(OptionBuilder.hasArg().withDescription(
				"do not generate DAO class").create("nodao"));

		opt.addOption(OptionBuilder.hasArg().withDescription(
				"do not generate DAO class").create("prepack"));

		opt.addOption(OptionBuilder.hasArg().withDescription(
				"do not generate DAO class").create("copyright"));

		opt.addOption(OptionBuilder.hasArg().withDescription(
				"do not generate DAO class").create("author"));

		//		
		cmdLine = parser.parse(opt, args);
		poCfgFile = cmdLine.getOptionValue("i");

		dependCfgFiles = cmdLine.getOptionValues("dep");

		impDestPath = cmdLine.getOptionValue("imp");
		apiDestPath = cmdLine.getOptionValue("api");
		if (cmdLine.hasOption("cfg")) {
			cfgDestPath = cmdLine.getOptionValue("cfg");
		}
		if (cmdLine.hasOption("prepack")) {
			prePackName = cmdLine.getOptionValue("prepack");
		}
		if (cmdLine.hasOption("nodesc")) {
			genDescClass = false;
		}
		if (cmdLine.hasOption("nodao")) {
			genDAOClass = false;
		}
		if (cmdLine.hasOption("copyright")) {
			copyright = cmdLine.getOptionValue("copyright");
		}
		if (cmdLine.hasOption("author")) {
			author = cmdLine.getOptionValue("author");
		}
		System.out.println(new StringBuffer().append("PO config file:\u0009\t")
				.append(poCfgFile).toString());
		//		
		if (dependCfgFiles != null) {
			System.out.println("Dependent PO config files:");

			for (int j = 0; j < dependCfgFiles.length; j++) {
				System.out.println(new StringBuffer().append("\t").append(
						dependCfgFiles[j]).toString());
			}
			//			
		}
		System.out.println(new StringBuffer()
				.append("Implement output path:\t").append(impDestPath)
				.toString());
		System.out.println(new StringBuffer().append("API output path:\t")
				.append(apiDestPath).toString());
		System.out.println(new StringBuffer().append("Config output path:\t")
				.append(cfgDestPath).toString());
		System.out.println(new StringBuffer().append("Package prefix:\t")
				.append(prePackName).toString());
		System.out.println(new StringBuffer().append(
				"Generate PO Descriptor:\t").append(genDescClass).toString());
		System.out.println(new StringBuffer().append("Generate DAO class:\t")
				.append(genDAOClass).toString());
	}

	public void loadConfig() {

		logger.debug("Begin to load PO configuration...");
		poRepository.setMainDef(poCfgFile, prePackName);
		int len = (this.dependCfgFiles == null) ? 0
				: this.dependCfgFiles.length;

		for (int i = 0; i < len; ++i) {
			this.poRepository.addPOConfig(this.dependCfgFiles[i]);
		}
		logger.debug("Load PO configuration succeed");

	}

	public void performGen() throws Exception {

		BasePOGenerator generator = null;

		logger.debug("Begin to generate PO API file");
		generator = new ApiGenerator();
		generator.setCopyright(this.copyright);
		generator.setAuthor(this.author);
		generator.init(this.poRepository, this.apiDestPath);
		generator.performGen();
		logger.debug("End generate PO API file");

		logger.debug("Begin to generate PO implement file");
		generator = new ImpGenerator();
		generator.setCopyright(this.copyright);
		generator.setAuthor(this.author);
		generator.init(this.poRepository, this.impDestPath);
		generator.performGen();
		
		logger.debug("End generate PO implement file");
		
		
		if (this.genDescClass)
	    {
	      logger.debug("Begin to generate PO description file");
	      generator = new DescGenerator();
	      generator.setCopyright(this.copyright);
	      generator.setAuthor(this.author);
	      generator.init(this.poRepository, this.impDestPath);
	      generator.performGen();
	      logger.debug("End generate PO description file");
	    }

	    if (!(this.genDAOClass)) {
	      return;
	    }
	    
//	    logger.debug("Begin to generate embed object query API file");
//	    generator = new EmbedQueryApiGenerator();
//	    generator.setCopyright(this.copyright);
//	    generator.setAuthor(this.author);
//	    generator.init(this.poRepository, this.apiDestPath);
//	    generator.performGen();
//	    logger.debug("End generate embed object query API file");
//
	    logger.debug("Begin to generate DAO API file");
	    generator = new ApiGenerator();
	    generator.setCopyright(this.copyright);
	    generator.setAuthor(this.author);
	    generator.init(this.poRepository, this.apiDestPath);
	    generator.performGen();
	    logger.debug("End generate DAO API file");

	    logger.debug("Begin to generate DAO implement file");
	    generator = new org.googlecode.viewt.core.tools.dao.ImpGenerator();
	    generator.setCopyright(this.copyright);
	    generator.setAuthor(this.author);
	    generator.init(this.poRepository, this.impDestPath);
	    generator.performGen();
	    logger.debug("End generate DAO implement file");
//
//	    logger.debug("Begin to generate embed object DAO API file");
//	    generator = new EmbedDAOApiGenerator();
//	    generator.setCopyright(this.copyright);
//	    generator.setAuthor(this.author);
//	    generator.init(this.poRepository, this.apiDestPath);
//	    generator.performGen();
//	    logger.debug("End generate embed object DAO API file");
//
//	    logger.debug("Begin to generate embed object DAO implement file");
//	    generator = new EmbedDAOImpGenerator();
//	    generator.setCopyright(this.copyright);
//	    generator.setAuthor(this.author);
//	    generator.init(this.poRepository, this.impDestPath);
//	    generator.performGen();
//	    logger.debug("End generate embed object DAO implement file");
//
//	    logger.debug("Begin to generate embed data config file");
//	    generator = new EmbedConfigGenerator();
//	    generator.setCopyright(this.copyright);
//	    generator.setAuthor(this.author);
//	    generator.init(this.poRepository, this.cfgDestPath);
//	    generator.performGen();
//	    logger.debug("End generate embed data config file");
//
//	    logger.debug("Begin to generate named sql config file");
//	    generator = new EmbedNamedSqlCfgGenerator();
//	    generator.setCopyright(this.copyright);
//	    generator.setAuthor(this.author);
//	    generator.init(this.poRepository, this.cfgDestPath);
//	    generator.performGen();
//	    logger.debug("End generate named sql config file");
//
	    logger.debug("Begin to generate DAO constant file");
	    generator = new ConstantGenerator();
	    generator.setCopyright(this.copyright);
	    generator.setAuthor(this.author);
	    generator.init(this.poRepository, this.apiDestPath);
	    ((ConstantGenerator)generator).setConfigPath(this.cfgDestPath);
	    generator.performGen();
	    logger.debug("End generate DAO constant file");
//
	    logger.debug("Begin to generate DAO bean config");
	    generator = new BeanConfigGenerator();
	    generator.setCopyright(this.copyright);
	    generator.setAuthor(this.author);
	    generator.init(this.poRepository, this.cfgDestPath);
	    generator.performGen();
	    logger.debug("End generate DAO bean config");

	    logger.debug("Begin to generate base data service");
	    generator = new BaseServiceGenerator();
	    generator.setCopyright(this.copyright);
	    generator.setAuthor(this.author);
	    generator.init(this.poRepository, this.impDestPath);
	    generator.performGen();
	    logger.debug("End generate base data service");
	    
	    
	}

	public static void main(String[] args) {
		POGenerateCommand command;

		System.out
				.println("Persistent Object generator, Copyright (c) 2006-2008 Leadron Information Technoloy co.,Ltd.");

		try {
			command = new POGenerateCommand();
			command.parseArgs(args);
			command.loadConfig();
			command.performGen();
		} catch (ParseException parseEx) {
			System.out.println("Invalid command line argument, check the doc");
			System.out.println(parseEx.getMessage());
			System.exit(-1);
		} catch (Exception ex) {
			System.out.println("Generate persistent object source file fail");
			ex.printStackTrace();
			System.exit(-1);
		}
		System.out.println("Generation done.");
	}

}
